package utils

import (
	"bufio"
	"errors"
	"io"
	"io/fs"
	"os"
	"path/filepath"
)

// ReadTextFile 读取文本文件的内容并返回字符串
func ReadTextFile(filename string) (string, error) {
	// 使用 os.ReadFile 函数读取指定文件的内容
	data, err := os.ReadFile(filepath.Clean(filename))
	if err != nil {
		return "", err
	}
	return string(data), nil
}

// ReadLinesFromFile 读取文件的每一行并返回一个字符串列表
// 参数：
//
//	filename - 要读取的文件的路径
//
// 返回值：
//
//	[]string - 包含文件中每一行的字符串列表
//	error - 如果读取文件出错，将返回一个错误
func ReadLinesFromFile(filename string) ([]string, error) {
	// 打开文件
	file, err := os.Open(filepath.Clean(filename))
	if err != nil {
		return nil, err // 如果打开文件失败，返回一个错误
	}
	defer file.Close() // 确保在函数返回前关闭文件

	var lines []string                // 创建一个字符串切片，用于存储文件的每一行
	scanner := bufio.NewScanner(file) // 创建一个文件扫描器，用于逐行读取文件内容
	for scanner.Scan() {              // 循环读取文件的每一行
		lines = append(lines, scanner.Text()) // 将每一行的内容追加到切片中
	}

	if err := scanner.Err(); err != nil { // 检查文件扫描是否出错
		return nil, err // 如果出错，返回一个错误
	}

	return lines, nil // 返回读取的所有行以及 nil 错误（如果没有错误）
}

// WriteTextFile 将文本内容写入文件
func WriteTextFile(filename, content string) error {
	// 使用 os.WriteFile 函数写入文本内容到指定文件
	return os.WriteFile(filepath.Clean(filename), []byte(content), 0644)
}

// CheckFileExists 检查文件是否存在
func CheckFileExists(filename string) (bool, error) {
	_, err := os.Stat(filepath.Clean(filename))
	if err == nil {
		return true, nil
	}
	if errors.Is(err, fs.ErrNotExist) {
		return false, nil
	}
	return false, err
}

// DeleteFile 删除文件
func DeleteFile(filename string) error {
	return os.Remove(filepath.Clean(filename))
}

// CopyFile 复制文件
func CopyFile(src, dst string) error {
	// 打开源文件
	input, err := os.Open(filepath.Clean(src))
	if err != nil {
		return err
	}
	defer input.Close()

	// 创建目标文件
	output, err := os.Create(filepath.Clean(dst))
	if err != nil {
		return err
	}
	defer output.Close()

	// 复制源文件内容到目标文件
	_, err = io.Copy(output, input)
	return err
}

// MoveFile 移动文件
func MoveFile(src, dst string) error {
	err := os.Rename(filepath.Clean(src), filepath.Clean(dst))
	return err
}

// CreateDirectory 创建指定路径下的目录（包括中间不存在的目录）。
// 参数 path 指定要创建的目录路径。
// 返回可能的错误信息，如果创建成功则返回 nil。
//
// 使用 os.MkdirAll 函数创建目录，并设置权限为 0755（读写权限给所有者，只读权限给其他用户）。
func CreateDirectory(path string) error {
	return os.MkdirAll(filepath.Clean(path), 0755)
}

// DeleteDirectory 删除指定路径下的目录及其所有内容。
// 参数 path 指定要删除的目录路径。
// 返回可能的错误信息，如果删除成功则返回 nil。
func DeleteDirectory(path string) error {
	// 使用 os.RemoveAll 函数递归删除指定目录及其所有内容。
	return os.RemoveAll(filepath.Clean(path))
}

// ListDirectoryContents 列出指定目录中的文件和子目录的名称列表。
// 参数 path 指定要列出内容的目录路径。
// 返回一个包含文件和子目录名称的字符串切片以及可能的错误信息。
func ListDirectoryContents(path string) ([]string, error) {
	// 使用 os.ReadDir 函数读取目录的条目列表。
	entries, err := os.ReadDir(filepath.Clean(path))
	if err != nil {
		return nil, err
	}

	var files []string
	for _, entry := range entries {
		// 如果能够获取条目信息并没有错误，则将其名称添加到列表中。
		if info, err := entry.Info(); err == nil {
			files = append(files, info.Name())
		}
	}
	// 返回文件和子目录名称列表以及可能的错误信息。
	return files, nil
}
